package parsers;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.lightysoft.logmx.business.ParsedEntry;
import com.lightysoft.logmx.mgr.LogFileParser;

/**
 * 
 * @author aprokofjev
 * 
 */
public abstract class BaseLogFileParser extends LogFileParser {
    private static final int MAX_MESSAGE_SIZE = 200;

    private ParsedEntry mEntry; // current parsed log entry
    private StringBuilder mEntryMsgBuffer;

    private SimpleDateFormat mDateFormat;

    @Override
    public abstract String getSupportedFileType();

    @Override
    protected final void parseLine(String line) throws Exception {
        // If end of file, records last entry if necessary, and exits
        if (line == null) {
            recordPreviousEntryIfExists();
            return;
        }

        if (!addLine(line) && mEntry != null) {
            mEntryMsgBuffer.append('\n').append(line); // appends this line to previous entry's text
        }
    }

    protected abstract boolean addLine(String line) throws Exception;

    protected void putExtraValue(String key, String val) {
        mEntry.getUserDefinedFields().put(key, val);
    }

    @Override
    public abstract String getParserName();

    @Override
    public Date getRelativeEntryDate(ParsedEntry parseEntry) throws Exception {
        return getSimpleDateFormat().parse(parseEntry.getDate());
    }

    @Override
    public Date getAbsoluteEntryDate(ParsedEntry parseEntry) throws Exception {
        Date date = getRelativeEntryDate(parseEntry);
        return getSimpleDateFormat().parse(mDateFormat.format(date));
    }

    @Override
    public List<String> getUserDefinedFields() {
        return new ArrayList<String>();
    };

    public abstract String getDateFromLine(String line);

    public abstract String getPID(String line);

    public abstract String getEmitter(String line);

    public abstract String getLogLevel(String line);

    public abstract String getMessage(String line);

    public abstract String getDateFormat();

    private SimpleDateFormat getSimpleDateFormat() {
        if (mDateFormat == null) {
            mDateFormat = new SimpleDateFormat(getDateFormat(), getLocale());
        }
        return mDateFormat;
    }

    public ParsedEntry createNewBlankLogEntry() {
        return createNewEntry();
    }

    /**
     * Send to LogMX the current parsed log entry.
     * 
     * @throws Exception
     */
    protected void recordPreviousEntryIfExists() throws Exception {
        if (mEntry != null) {
            mEntry.setMessage(mEntryMsgBuffer.toString());
            addEntry(mEntry);
        }
    }

    /**
     * Send to LogMX the current parsed log entry, then create a new one.
     * 
     * @throws Exception
     */
    protected void prepareNewEntry() throws Exception {
        recordPreviousEntryIfExists();
        mEntry = createNewEntry();
        mEntryMsgBuffer = new StringBuilder(MAX_MESSAGE_SIZE);
        mEntry.setUserDefinedFields(new HashMap<String, Object>(1));
    }

    protected void fillEntry(String line) throws Exception {
        mEntry.setDate(getDateFromLine(line));
        mEntry.setEmitter(getEmitter(line));
        mEntry.setThread(getPID(line));
        mEntry.setLevel(getLogLevel(line));
        mEntryMsgBuffer.append(getMessage(line).trim());
    }

}
